<template>
  <div class="mb-2">
    <span class="mr-4" :class="{ 'ant-form-label-mark': requiredMark }">{{ title || "后台权限" }}</span>
    <a-checkbox
      v-if="isUpdate"
      class="!mr-2"
      :checked="allManageChecked"
      :indeterminate="allManageIndeterminate"
      @change="allManageChange"
    >
      <span class="mr-2">{{ t("aiot.role.allManageAuth") }}</span>
      <span class="text-color-secondary text-sm">{{ t("aiot.role.manageAuthDetail") }}</span>
    </a-checkbox>
    <a-checkbox
      v-if="isUpdate"
      class="!ml-0"
      :checked="allManageChecked || allCheckChecked"
      :disabled="allManageChecked"
      :indeterminate="allCheckedIndeterminate"
      @change="allCheckChange"
    >
      <span class="mr-2">{{ t("aiot.role.allCheckAuth") }}</span>
      <span class="text-color-secondary text-sm">{{ t("aiot.role.checkAuthDetail") }}</span>
    </a-checkbox>
  </div>
  <div class="rounded border border-solid border-color-split">
    <div class="border-0 border-b border-solid border-color-split hidden md:flex md:flex-row md:items-center">
      <div class="p-4 bg-header text-color-header text-lg font-semibold" :class="[isUpdate ? 'sm:w-99' : 'sm:w-34']">
        {{ t("aiot.role.featureAuth") }}
      </div>
      <div class="flex-1 p-4 text-color-header text-lg font-semibold border-0 border-l border-solid border-color-split">
        {{ t("aiot.role.pageAuth") }}
      </div>
    </div>
    <div
      v-for="(el, j) in innerData"
      :key="el.functionId"
      class="md:flex md:flex-row md:items-center bg-header"
      :class="{ 'border-0 border-b border-solid border-color-split': j !== innerData.length - 1 }"
    >
      <div class="sm:p-4" :class="[isUpdate ? 'sm:w-99 p-4' : 'sm:w-34 p-2']">
        <AuthItem
          v-model:manageChecked="el._manageChecked"
          v-model:checkChecked="el._checkChecked"
          :manage-indeterminate="el._manageIndeterminate"
          :check-indeterminate="el._checkIndeterminate"
          :name="el.title || t(`routes.${el.name}`)"
          :is-update="isUpdate"
          :disabled="el.disabled"
          @change="change(el, $event)"
        />
      </div>
      <div
        class="flex-1 sm:p-4 bg-white border-0 md:border-l border-solid border-color-split"
        :class="[isUpdate ? 'p-4' : 'p-2']"
      >
        <AuthItem
          v-if="el.type === MenuType.FUNCTION"
          v-model:manageChecked="el._manageChecked"
          v-model:checkChecked="el._checkChecked"
          :name="el.title || t(`routes.${el.name}`)"
          :is-update="isUpdate"
          :show-auth-text="true"
          :disabled="el.disabled"
          @change="change(el, $event)"
        />
        <div v-else-if="el.children && el.children.length > 0">
          <AuthItem
            v-for="(page, i) in el.children"
            :key="page.functionId"
            v-model:manageChecked="page._manageChecked"
            v-model:checkChecked="page._checkChecked"
            :class="{ 'mb-4': i !== el.children.length - 1 }"
            :name="page.title || t(`routes.${page.name}`)"
            :is-update="isUpdate"
            :show-auth-text="true"
            :disabled="page.disabled"
            @change="change(page, $event)"
          />
        </div>
      </div>
    </div>
  </div>
</template>
<script lang="ts" setup>
import { PartialMenuItem, MenuType } from "/@/api/aiot/menu/models";
import { useI18n } from "/@/locales/useI18n";
import AuthItem from "./AuthItem.vue";
import { nextTick, ref, watch } from "vue";
import { findItemByKey, loopItem } from "/@/utils/treeData";
import { OperPermissionType, AuthorizedRoleFunctionsParams, RoleFunctionMenuItem } from "/@/api/aiot/role/models";
import { useApplicationStore } from "/@/stores/aiot/application";
import { cloneDeep } from "lodash-es";
import { useMenuStore } from "/@/stores/aiot/menu";
import { PROJECT_DETAIL_ROUTE_NAME } from "/@/router";

const { t } = useI18n();
//不需处理权限的菜单的action集
const unDealMenuActions = [`/${PROJECT_DETAIL_ROUTE_NAME}`];
/**
 * 对于管理员角色来说那些不能修改的默认勾选的菜单名称key，对应locales中的routes
 */
// const READONLY_AUTH_ADMIN = ["userManage", "userManageSub", "userGroupManage", "roleManage", "authManage"];
const props = defineProps<{
  title?: string;
  isAdmin?: boolean;
  //是否可以更新（勾选）权限
  isUpdate?: boolean;
  data?: PartialMenuItem[];
  //发送给服务器的权限值
  value?: AuthorizedRoleFunctionsParams;
  //服务器返回回来的权限值
  serverValue?: RoleFunctionMenuItem[];
  requiredMark?: boolean;
}>();
const menuStore = useMenuStore();
function handleMenuData(data: PartialMenuItem[]) {
  const copyData = cloneDeep(data);
  loopItem(
    copyData,
    (item, i, items) => {
      if (unDealMenuActions.includes(item.action as string)) {
        items.splice(i, 1);
      }
    },
    null,
    true
  );
  return copyData;
}
const innerData = ref<PartialMenuItem[]>(handleMenuData(props.data || menuStore.menuData));
const emits = defineEmits(["update:value"]);
function getLeftWidth() {
  return props.isUpdate ? 348 : 120;
}
const leftWidth = ref(getLeftWidth());
watch(
  () => props.isUpdate,
  () => {
    leftWidth.value = getLeftWidth();
  }
);

const allManageChecked = ref(false);
const allCheckChecked = ref(false);
const allManageIndeterminate = ref(false);
const allCheckedIndeterminate = ref(false);

function allManageChange(e) {
  let checked = false;
  if (typeof e == "boolean") {
    checked = e;
  } else {
    checked = (e.target as HTMLInputElement).checked;
  }
  allManageChecked.value = checked;
  allCheckChecked.value = checked;
  let hasDisabledForAll = false;
  let hasChDisabled = false;
  innerData.value.forEach((el) => {
    if (el.disabled) {
      hasDisabledForAll = true;
      return;
    }
    el._manageChecked = checked;
    el._checkChecked = checked;
    if (checked) {
      el._manageIndeterminate = false;
      el._checkIndeterminate = false;
      if (el.type === MenuType.FEATURE && el.children) {
        el.children.forEach((ch) => {
          ch._manageChecked = true;
          ch._manageIndeterminate = false;
          ch._checkChecked = true;
          ch._checkIndeterminate = false;
        });
      }
    } else {
      if (el.type === MenuType.FEATURE && el.children) {
        let hasDisabled = false;
        el.children.forEach((ch) => {
          if (ch.disabled) {
            hasDisabled = true;
            hasChDisabled = true;
            return;
          }
          ch._manageChecked = false;
          ch._manageIndeterminate = false;
          ch._checkChecked = false;
          ch._checkIndeterminate = false;
        });
        el._manageIndeterminate = hasDisabled;
        el._checkIndeterminate = hasDisabled;
      }
    }
  });
  if (checked) {
    allManageIndeterminate.value = false;
    allCheckedIndeterminate.value = false;
  } else {
    allManageIndeterminate.value = hasDisabledForAll || hasChDisabled;
    allCheckedIndeterminate.value = hasDisabledForAll || hasChDisabled;
  }
  updateValue();
}

function allCheckChange(e) {
  const checked = (e.target as HTMLInputElement).checked;
  allCheckChecked.value = checked;
  let hasDisabled = false;
  innerData.value.forEach((el) => {
    el._checkChecked = checked;
    el._checkIndeterminate = false;
    if (el.disabled) {
      hasDisabled = true;
    }
    if (el.children) {
      el.children.forEach((ch) => {
        ch._checkChecked = checked;
      });
    }
  });
  if (checked) {
    allCheckedIndeterminate.value = false;
  } else {
    allCheckedIndeterminate.value = hasDisabled;
  }
  updateValue();
}

//刷新两个总checkbox的勾选状态
function refreshAllStatus() {
  let isAllManageChecked = true;
  let isAllCheckChecked = true;
  let hasDisabled = false;
  let isAllManageUnChecked = true;
  let isAllCheckUnChecked = true;
  let hasManageIndeterminate = false;
  let hasCheckIndeterminate = false;
  innerData.value.forEach((el) => {
    if (el.disabled) {
      hasDisabled = true;
    }
    if (el._manageChecked) {
      isAllManageUnChecked = false;
      isAllCheckUnChecked = false;
    } else {
      isAllManageChecked = false;
      if (el._checkChecked) {
        isAllCheckUnChecked = false;
      } else {
        isAllCheckChecked = false;
      }
    }
    if (el._manageIndeterminate) {
      hasManageIndeterminate = true;
    }
    if (el._checkIndeterminate) {
      hasCheckIndeterminate = true;
    }
  });
  if (isAllManageChecked) {
    allManageChecked.value = true;
    allCheckChecked.value = true;
    allManageIndeterminate.value = false;
    allCheckedIndeterminate.value = false;
  } else {
    allManageChecked.value = false;
    allManageIndeterminate.value = hasDisabled || !isAllManageUnChecked || hasManageIndeterminate;
    if (isAllCheckChecked) {
      allCheckChecked.value = true;
      allCheckedIndeterminate.value = false;
    } else {
      allCheckChecked.value = false;
      allCheckedIndeterminate.value =
        hasDisabled || !isAllCheckUnChecked || hasCheckIndeterminate || hasManageIndeterminate;
    }
  }
}

let isTriggerChange = true;
//用户点击勾选才会触发change，程序代码设置勾选不会触发
function change(el: PartialMenuItem, { type, checked }: { type: "manageChecked" | "checkChecked"; checked: boolean }) {
  if (!isTriggerChange) return;
  if (el.type === MenuType.FEATURE) {
    if (type === "manageChecked") {
      if (checked) {
        el.children?.forEach((ch) => {
          ch._manageChecked = true;
        });
      } else {
        el._checkChecked = false;
        let hasDisabled = false;
        el.children?.forEach((ch) => {
          if (ch.disabled) {
            hasDisabled = true;
            return;
          }
          ch._manageChecked = false;
          ch._checkChecked = false;
        });
        el._checkIndeterminate = hasDisabled;
        el._manageIndeterminate = hasDisabled;
      }
    } else {
      if (checked) {
        el.children?.forEach((ch) => {
          ch._checkChecked = true;
        });
      } else {
        let hasDisabled = false;
        el.children?.forEach((ch) => {
          if (ch.disabled) {
            hasDisabled = true;
            return;
          }
          ch._checkChecked = false;
        });
        el._checkIndeterminate = hasDisabled;
      }
    }
  } else {
    const info = findItemByKey(innerData.value, el.functionId as string, "functionId");
    if (info && info.parent) {
      //是否全部勾选了
      let isAllChecked = true;
      //是否全部未勾选
      let isAllUnChecked = true;
      //是否半选
      let isIndeterminate = false;
      for (let i = 0; i < info.items.length; i++) {
        if (info.items[i][`_${type}`]) {
          isAllUnChecked = false;
          isIndeterminate = true;
        } else {
          isAllChecked = false;
        }
      }
      const indeterminateKey = type === "manageChecked" ? "_manageIndeterminate" : "_checkIndeterminate";
      if (isAllUnChecked) {
        info.parent[indeterminateKey] = false;
      } else if (isIndeterminate) {
        info.parent[indeterminateKey] = true;
      }
      info.parent[`_${type}`] = isAllChecked;
    }
  }
  refreshAllStatus();
  updateValue();
}

const appStore = useApplicationStore();
let isTriggerUpdate = true;
function updateValue() {
  if (!isTriggerUpdate) return;
  const roleFolderPermissions: AuthorizedRoleFunctionsParams["roleFolderPermissions"] = [];
  const roleMenuPermissions: AuthorizedRoleFunctionsParams["roleMenuPermissions"] = [];
  innerData.value.forEach((el) => {
    if (el.type === MenuType.FEATURE) {
      if (el._manageChecked || el._checkChecked || el._manageIndeterminate || el._checkIndeterminate) {
        roleFolderPermissions.push({
          applicationId: appStore.curAppId,
          functionId: el.functionId as string,
        });
        el.children?.forEach((ch) => {
          const pagePermission = getPagePermission(ch);
          if (pagePermission) {
            roleMenuPermissions.push(pagePermission);
          }
        });
      }
    } else {
      const pagePermission = getPagePermission(el);
      if (pagePermission) {
        roleMenuPermissions.push(pagePermission);
      }
    }
  });
  isTriggerWatch = false;
  emits("update:value", {
    roleFolderPermissions,
    roleMenuPermissions,
  });
  nextTick(() => {
    isTriggerWatch = true;
  });
}
function getPagePermission(el: PartialMenuItem) {
  if (el._manageChecked || el._checkChecked) {
    return {
      applicationId: appStore.curAppId,
      functionId: el.functionId as string,
      operationType: el._manageChecked ? OperPermissionType.MANAGE : OperPermissionType.CHECK,
      parentFuntionId: "",
    };
  }
}
//刷新第一层的勾选状态
function refreshFeatureCheck() {
  innerData.value.forEach((el) => {
    if (el.type !== MenuType.FEATURE) return;
    let manageIndeterminate = false;
    let isAllChManageChecked = true;
    let checkIndeterminate = false;
    let isAllChCheckChecked = true;
    if (el.children && el.children.length > 0) {
      el.children.forEach((ch) => {
        if (ch._manageChecked) {
          manageIndeterminate = true;
        } else {
          isAllChManageChecked = false;
        }
        if (ch._checkChecked) {
          checkIndeterminate = true;
        } else {
          isAllChCheckChecked = false;
        }
      });
      el._manageIndeterminate = manageIndeterminate;
      el._manageChecked = isAllChManageChecked;
      if (!isAllChManageChecked) {
        el._checkIndeterminate = checkIndeterminate;
        el._checkChecked = isAllChCheckChecked;
      }
    }
  });
}
//
function toggleReadonlyAuth(checked: boolean) {
  loopItem(innerData.value, (item) => {
    item.disabled = checked;
    item._manageChecked = checked;
    item._manageIndeterminate = false;
  });
}
watch(
  () => props.isAdmin,
  (v) => {
    if (v) {
      //管理员情况下将那些不能改的权限勾选上
      toggleReadonlyAuth(true);
    } else {
      toggleReadonlyAuth(false);
    }
  },
  {
    immediate: false,
  }
);
let isTriggerWatch = true;
watch(
  () => props.serverValue,
  async (v) => {
    if (!isTriggerWatch) return;
    if (!v) {
      v = [];
    }
    isTriggerUpdate = false;
    isTriggerChange = false;
    //先重置
    allManageChange(false);
    loopItem(innerData.value, (item) => {
      item._manageChecked = false;
      item._manageIndeterminate = false;
      item._checkChecked = false;
      item._checkIndeterminate = false;
    });
    await nextTick();
    isTriggerChange = true;
    isTriggerUpdate = true;
    //再根据权限值设置值
    v.forEach((el) => {
      if (!el.isFolder) {
        const target = findItemByKey(innerData.value, el.functionId as string, "functionId");
        if (target) {
          const type = el.operationsType || el.operationType;
          if (type === OperPermissionType.MANAGE) {
            target.item._manageChecked = true;
          } else if (type === OperPermissionType.CHECK) {
            target.item._checkChecked = true;
          }
        }
      }
    });
    if (props.isAdmin) {
      toggleReadonlyAuth(true);
    }
    refreshFeatureCheck();
    refreshAllStatus();
    updateValue();
  },
  {
    immediate: true,
  }
);
</script>
